"""
Flask主应用模块
作者：资深Flask讲师
功能：应用初始化、拦截器、蓝图注册
"""

from flask import Flask, request, jsonify
from flask_cors import CORS
from myflask.config.config_dev import DevelopmentConfig
from myflask.tools.myjwt import JWTUtil
from myflask.tools.myredis import RedisUtil
from myflask.tools.bd import init_db

# 创建Flask应用实例
app = Flask(__name__)

# 加载配置
app.config.from_object(DevelopmentConfig)

# 初始化数据库
init_db(app)

# 配置CORS（跨域资源共享）
CORS(app, resources={
    r"/api/*": {
        "origins": DevelopmentConfig.CORS_ORIGINS,
        "methods": ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
        "allow_headers": ["Content-Type", "Authorization"],
        "expose_headers": ["Content-Type", "Authorization"],
        "supports_credentials": True
    }
})

# 注册蓝图（路由模块）
from myflask.views.user import user_blue
from myflask.views.orders import orders_blue
from myflask.views.employee import employee_blue
from myflask.views.department import department_blue
from myflask.views.leave import leave_blue

app.register_blueprint(user_blue, url_prefix='/api/user')
app.register_blueprint(orders_blue, url_prefix='/api/orders')
app.register_blueprint(employee_blue, url_prefix='/api/employee')
app.register_blueprint(department_blue, url_prefix='/api/department')
app.register_blueprint(leave_blue, url_prefix='/api/leave')


@app.before_request
def before_request_handler():
    """
    请求拦截器 - 多维度Token验证
    1. OPTIONS请求放行（CORS预检）
    2. 白名单检查（登录、注册等接口无需token）
    3. Token存在性检查
    4. Token格式检查
    5. Redis黑名单检查（退出登录后的token）
    6. JWT解码验证（签名、过期时间）
    """
    
    # OPTIONS请求直接放行（CORS预检）
    if request.method == 'OPTIONS':
        return None
    
    # 白名单检查（登录、注册等接口无需token）
    WHITE_LIST = DevelopmentConfig.WHITE_LIST
    if request.path in WHITE_LIST:
        return None
    
    # 提取token
    auth_header = request.headers.get('Authorization')
    if not auth_header:
        return jsonify({"code": 401, "message": "未提供Token，请先登录", "data": None}), 401
    
    if not auth_header.startswith('Bearer '):
        return jsonify({"code": 401, "message": "Token格式错误", "data": None}), 401
    
    token = auth_header[7:]
    
    # 检查黑名单（退出登录后的token）
    if RedisUtil.is_in_blacklist(token):
        return jsonify({"code": 401, "message": "Token已失效，请重新登录", "data": None}), 401
    
    # JWT验证（签名、过期时间）
    try:
        payload = JWTUtil.decode(token)
        # 将用户信息附加到request对象，后续接口可直接使用
        request.user_info = payload
        return None
    except Exception as e:
        return jsonify({"code": 401, "message": f"Token验证失败: {str(e)}", "data": None}), 401


@app.route('/')
def index():
    """Root endpoint"""
    return jsonify({"code": 200, "message": "Flask JWT API Server is running!", "data": {"version": "1.0.0"}})


@app.errorhandler(404)
def not_found(error):
    return jsonify({"code": 404, "message": "Not found", "data": None}), 404


@app.errorhandler(500)
def internal_error(error):
    return jsonify({"code": 500, "message": "Internal server error", "data": None}), 500


